package com.xing.cglib.source;

import com.xing.asm.simple.MyClassLoader;
import com.xing.cglib.cgtest.TestEx;
import com.xing.jvmsandbox.WeaveManager;
import com.xing.jvmsandbox.event.BeforeEvent;
import com.xing.jvmsandbox.event.Event;
import com.xing.jvmsandbox.filter.Filter;
import com.xing.jvmsandbox.listener.EventListener;
import com.xing.jvmsandbox.util.SandboxStringUtils;
import com.xing.jvmsandbox.weave.DefaultTransformer;
import com.xing.jvmsandbox.weave.Transformer;
import com.xing.jvmsandbox.weave.test.Computer;
import org.apache.commons.io.IOUtils;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class EhMain {

    public static void main(String[] args) throws Throwable{

        Eh eh = new Eh();
        eh.setSuperclass(TestEx.class);

        byte[] sourceCode = toByteArray(TestEx.class);
        ClassReader cr = new ClassReader(sourceCode);
        ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
        ClassVisitor cv = new ClassVisitor(Opcodes.ASM5, cw) {
            @Override
            public void visit(int i, int i1, String s, String s1, String s2, String[] strings) {
                super.visit(i, i1, s, s1, s2, strings);
            }
        };

        eh.generateClass(cv);

        byte[] newCode = cw.toByteArray();

        FileOutputStream fos = new FileOutputStream("E:\\ljx\\asm\\LJX$TestEx.class");
        fos.write(newCode);
        fos.close();


        MyClassLoader myClassLoader = new MyClassLoader(Thread.currentThread().getContextClassLoader());
        Class clazz = myClassLoader.defineClass(null, newCode);
        Object instance = clazz.newInstance();

        TestEx t = (TestEx) instance;

        t.excute();

        System.err.println(instance);




        EventListener eventListener = new EventListener() {
            @Override
            public void onEvent(Event event) throws Throwable {
                if(event instanceof BeforeEvent) {
                    System.err.println("hello, 我进来了啦");
                }
            }
        };

//        Class<?> computerClass = WeaveManager.getSingleton().weave(clazz, "excute", eventListener);

//        System.err.println(computerClass);


        final Transformer enhancer = new DefaultTransformer(
                new Filter() {
                    @Override
                    public boolean doClassFilter(final int access,
                                                 final String javaClassName,
                                                 final String superClassTypeJavaClassName,
                                                 final String[] interfaceTypeJavaClassNameArray) {
                        return true;
                    }

                    @Override
                    public boolean doMethodFilter(final int access,
                                                  final String javaMethodName,
                                                  final String[] parameterTypeJavaClassNameArray,
                                                  final String[] throwsTypeJavaClassNameArray) {
                        return true;
                    }
                },
                1
        );

        byte[] data = enhancer.toByteCodeArray(new MyClassLoader(Thread.currentThread().getContextClassLoader()), newCode);

        fos = new FileOutputStream("E:\\ljx\\asm\\LJX$$HHH.class");
        fos.write(data);
        fos.close();

    }

    public static byte[] toByteArray(final Class<?> targetClass) throws IOException {
        final InputStream is = targetClass.getResourceAsStream("/" + SandboxStringUtils.toInternalClassName(targetClass.getName()).concat(".class"));
        try {
            return IOUtils.toByteArray(is);
        } finally {
            IOUtils.closeQuietly(is);
        }
    }

}
